home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 676-700 / 681 / term / source.lha / Beep.c next >
C/C++ Source or Header  |  1992-05-09  |  7KB  |  370 lines

  1. /*
  2. **    $Id: Beep.c,v 1.3 92/05/01 12:52:01 olsen Sta Locker: olsen $
  3. **    $Revision: 1.3 $
  4. **    $Date: 92/05/01 12:52:01 $
  5. **
  6. **    Sound support routines
  7. **
  8. **    Copyright © 1990-1992 by Olaf `Olsen' Barthel & MXM
  9. **        All Rights Reserved
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14.     /* IFF Sound `8SVX' voice header. */
  15.  
  16. struct Voice8Header
  17. {
  18.     ULONG    oneShotHiSamples,    /* # samples in the high octave 1-shot part */
  19.         repeatHiSamples,    /* # samples in the high octave repeat part */
  20.         samplesPerHiCycle;    /* # samples/cycle in high octave, else 0 */
  21.     UWORD    samplesPerSec;        /* data sampling rate */
  22.     UBYTE    ctOctave,        /* # of octaves of waveforms */
  23.         sCompression;        /* data compression technique used */
  24.     LONG    volume;            /* playback nominal volume from 0 to Unity
  25.                      * (full volume). Map this value into
  26.                      * the output hardware's dynamic range.
  27.                      */
  28. };
  29.  
  30.     /* Small sound information. */
  31.  
  32. struct SoundInfo
  33. {
  34.     APTR    Data;        /* Data pointer. */
  35.  
  36.     LONG    Length;        /* Real length. */
  37.     ULONG    Rate;        /* Recording rate. */
  38.     WORD    Volume;        /* Sound volume. */
  39. };
  40.  
  41.     /* Local sound info. */
  42.  
  43. STATIC struct SoundInfo    SoundInfo;
  44. STATIC BYTE        HasSound    = FALSE,
  45.             SoundPlayed    = FALSE;
  46.  
  47.     /* CreateBeep():
  48.      *
  49.      *    Set up the audio.device for a decent beep sound.
  50.      */
  51.  
  52. BYTE
  53. CreateBeep()
  54. {
  55.         /* Do we already have the resources we need? */
  56.  
  57.     if(!AudioBlock)
  58.     {
  59.         struct MsgPort *AudioPort;
  60.  
  61.             /* No sound so far. */
  62.  
  63.         SoundPlayed = FALSE;
  64.  
  65.             /* Create the IO reply port. */
  66.  
  67.         if(AudioPort = (struct MsgPort *)CreateMsgPort())
  68.         {
  69.                 /* Create the audio IO info. */
  70.  
  71.             if(AudioBlock = (struct IOAudio *)CreateIORequest(AudioPort,sizeof(struct IOAudio)))
  72.             {
  73.                     /* Open audio.device */
  74.  
  75.                 if(!OpenDevice(AUDIONAME,0,AudioBlock,0))
  76.                     return(TRUE);
  77.  
  78.                 DeleteIORequest(AudioBlock);
  79.             }
  80.  
  81.             DeleteMsgPort(AudioPort);
  82.         }
  83.  
  84.         AudioBlock = NULL;
  85.  
  86.         return(FALSE);
  87.     }
  88.     else
  89.         return(TRUE);
  90. }
  91.  
  92.     /* DeleteBeep():
  93.      *
  94.      *    Remove the data allocated for the beep sound.
  95.      */
  96.  
  97. VOID
  98. DeleteBeep()
  99. {
  100.     if(AudioBlock)
  101.     {
  102.         if(AudioBlock -> ioa_Request . io_Device)
  103.             CloseDevice(AudioBlock);
  104.  
  105.         if(AudioBlock -> ioa_Request . io_Message . mn_ReplyPort)
  106.             DeleteMsgPort(AudioBlock -> ioa_Request . io_Message . mn_ReplyPort);
  107.  
  108.         DeleteIORequest(AudioBlock);
  109.  
  110.         AudioBlock = NULL;
  111.     }
  112.  
  113.     if(HasSound)
  114.     {
  115.         FreeVec(SoundInfo . Data);
  116.  
  117.         HasSound = FALSE;
  118.     }
  119. }
  120.  
  121.     /* ClearAudio():
  122.      *
  123.      *    Clear the audio control block for reuse.
  124.      */
  125.  
  126. VOID
  127. ClearAudio()
  128. {
  129.         /* Remove the request. */
  130.  
  131.     WaitIO(AudioBlock);
  132.  
  133.         /* Clear the signal bit. */
  134.  
  135.     SetSignal(0,SIG_AUDIO);
  136.  
  137.         /* Free the channels we had allocated. */
  138.  
  139.     AudioBlock -> ioa_Request . io_Command = ADCMD_FREE;
  140.  
  141.     DoIO(AudioBlock);
  142.  
  143.         /* No sound running. */
  144.  
  145.     SoundPlayed = FALSE;
  146. }
  147.  
  148.     /* Beep():
  149.      *
  150.      *    Produce a decent beep sound.
  151.      */
  152.  
  153. VOID
  154. Beep()
  155. {
  156.     if(AudioBlock)
  157.     {
  158.         BYTE PlayItAgainSam;    /* Note: `Sam' is Sam Dicker, the author of
  159.                      *       the original audio.device implementation.
  160.                      */
  161.  
  162.             /* AudioRequest has returned. */
  163.  
  164.         if(SetSignal(0,0) & SIG_AUDIO)
  165.             ClearAudio();
  166.  
  167.             /* Check whether we are to play the sound or not. */
  168.  
  169.         if(!SoundPlayed)
  170.             PlayItAgainSam = TRUE;
  171.         else
  172.         {
  173.             if(CheckIO(AudioBlock))
  174.                 PlayItAgainSam = TRUE;
  175.             else
  176.                 PlayItAgainSam = FALSE;
  177.         }
  178.  
  179.             /* May we play the sound? */
  180.  
  181.         if(PlayItAgainSam)
  182.         {
  183.                 /* Allocate a sound channel, we don't want to
  184.                  * wait for it, the `beep' sound is to played
  185.                  * right now.
  186.                  */
  187.  
  188.             AudioBlock -> ioa_Request . io_Command                = ADCMD_ALLOCATE;
  189.             AudioBlock -> ioa_Request . io_Flags                = ADIOF_NOWAIT | IOF_QUICK;
  190.             AudioBlock -> ioa_Request . io_Message . mn_Node . ln_Pri    = 80;
  191.             AudioBlock -> ioa_Data                        = AnyChannel;
  192.             AudioBlock -> ioa_Length                    = 4;
  193.  
  194.                 /* Try the allocation. */
  195.  
  196.             BeginIO(AudioBlock);
  197.  
  198.                 /* If still in progress, no channel is available yet. */
  199.  
  200.             if(!CheckIO(AudioBlock))
  201.             {
  202.                     /* Abort the allocation. */
  203.  
  204.                 AbortIO(AudioBlock);
  205.  
  206.                     /* Wait for request to be returned. */
  207.  
  208.                 WaitIO(AudioBlock);
  209.             }
  210.             else
  211.             {
  212.                     /* Wait for request to be returned. */
  213.  
  214.                 if(!WaitIO(AudioBlock))
  215.                 {
  216.                         /* Set up the sound IO data. */
  217.  
  218.                     if(HasSound)
  219.                     {
  220.                         AudioBlock -> ioa_Period    = SoundInfo . Rate;
  221.                         AudioBlock -> ioa_Volume    = SoundInfo . Volume;
  222.                         AudioBlock -> ioa_Cycles    = 1;
  223.                         AudioBlock -> ioa_Data        = SoundInfo . Data;
  224.                         AudioBlock -> ioa_Length    = SoundInfo . Length;
  225.                     }
  226.                     else
  227.                     {
  228.                         AudioBlock -> ioa_Period    = 223;
  229.                         AudioBlock -> ioa_Volume    = 64 / 2;
  230.                         AudioBlock -> ioa_Cycles    = 150;
  231.                         AudioBlock -> ioa_Data        = &SineWave[0];
  232.                         AudioBlock -> ioa_Length    = 8;
  233.                     }
  234.  
  235.                     AudioBlock -> ioa_Request . io_Command    = CMD_WRITE;
  236.                     AudioBlock -> ioa_Request . io_Flags    = ADIOF_PERVOL;
  237.  
  238.                         /* Start the sound. */
  239.  
  240.                     BeginIO(AudioBlock);
  241.  
  242.                     SoundPlayed = TRUE;
  243.                 }
  244.             }
  245.         }
  246.     }
  247. }
  248.  
  249.     /* OpenSound(UBYTE *Name):
  250.      *
  251.      *    Load an IFF-8SVX sound file instead of the standard
  252.      *    beep (yes, this is a zany feature nobody will ever need!).
  253.      */
  254.  
  255. BYTE
  256. OpenSound(UBYTE *Name)
  257. {
  258.     STATIC ULONG SoundProps[] = { '8SVX', 'VHDR' };
  259.  
  260.     struct IFFHandle    *Handle;
  261.     struct StoredProperty    *Prop;
  262.     struct Voice8Header    *VoiceHeader;
  263.  
  264.     BYTE             Success = FALSE;
  265.  
  266.         /* Allocate an IFF handle. */
  267.  
  268.     if(Handle = AllocIFF())
  269.     {
  270.             /* Open the file. */
  271.  
  272.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  273.         {
  274.                 /* Say it's a DOS file. */
  275.  
  276.             InitIFFasDOS(Handle);
  277.  
  278.                 /* Open the file for reading. */
  279.  
  280.             if(!OpenIFF(Handle,IFFF_READ))
  281.             {
  282.                     /* Remember VHDR-chunks encountered. */
  283.  
  284.                 if(!PropChunks(Handle,&SoundProps[0],1))
  285.                 {
  286.                         /* Stop at the body chunk. */
  287.  
  288.                     if(!StopChunk(Handle,'8SVX','BODY'))
  289.                     {
  290.                             /* Start scanning... */
  291.  
  292.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  293.                         {
  294.                                 /* Obtain the stored VHDR-chunk. */
  295.  
  296.                             if(Prop = FindProp(Handle,'8SVX','VHDR'))
  297.                             {
  298.                                 VoiceHeader = (struct Voice8Header *)Prop -> sp_Data;
  299.  
  300.                                     /* Compressed data not supported so far. */
  301.  
  302.                                 if(!VoiceHeader -> sCompression)
  303.                                 {
  304.                                     struct ContextNode *ContextNode;
  305.  
  306.                                         /* Inquire current chunk. */
  307.  
  308.                                     if(ContextNode = CurrentChunk(Handle))
  309.                                     {
  310.                                             /* We don't support double-buffering, this
  311.                                              * is only a *simple* example.
  312.                                              */
  313.  
  314.                                         if(ContextNode -> cn_Size < 102400)
  315.                                         {
  316.                                                 /* Allocate the data storage. */
  317.  
  318.                                             if(SoundInfo . Data = AllocVec(ContextNode -> cn_Size,MEMF_CHIP))
  319.                                             {
  320.                                                     /* Play either the one-shot or the continuous
  321.                                                      * part, not both.
  322.                                                      */
  323.  
  324.                                                 SoundInfo . Length    = VoiceHeader -> oneShotHiSamples ? VoiceHeader -> oneShotHiSamples : VoiceHeader -> repeatHiSamples;
  325.  
  326.                                                     /* Calculate recording rate. */
  327.  
  328.                                                 SoundInfo . Rate    = (GfxBase -> DisplayFlags & PAL ? 3546895 : 3579545) / VoiceHeader -> samplesPerSec;
  329.  
  330.                                                     /* Calculate volume. */
  331.  
  332.                                                 SoundInfo . Volume    = (VoiceHeader -> volume * 64) / 0x10000;
  333.  
  334.                                                     /* Read the data. */
  335.  
  336.                                                 if(ReadChunkBytes(Handle,SoundInfo . Data,ContextNode -> cn_Size))
  337.                                                     Success = TRUE;
  338.                                                 else
  339.                                                     FreeVec(SoundInfo . Data);
  340.                                             }
  341.                                         }
  342.                                     }
  343.                                 }
  344.                             }
  345.                         }
  346.                     }
  347.                 }
  348.  
  349.                     /* Make iffparse clean up after us. */
  350.  
  351.                 CloseIFF(Handle);
  352.             }
  353.  
  354.                 /* Close the DOS handle. */
  355.  
  356.             Close(Handle -> iff_Stream);
  357.         }
  358.  
  359.             /* Free the IFF handle. */
  360.  
  361.         FreeIFF(Handle);
  362.     }
  363.  
  364.         /* Remember success/failure. */
  365.  
  366.     HasSound = Success;
  367.  
  368.     return(Success);
  369. }
  370.